package cn.iocoder.yudao.module.trade.dal.mysql.order;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderSummaryRespVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 贵金属交易订单 Mapper
 *
 * @author 芋道源码
 */
@Mapper
public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {


    default int updateByNoAndStatus(String orderNo, Integer nowStatus, Integer afterStatus, Integer type) {
        return update(new LambdaUpdateWrapper<TradeOrderDO>()
                .eq(TradeOrderDO::getOrderNo, orderNo)
                .eq(TradeOrderDO::getStatus, nowStatus)
                .set(TradeOrderDO::getStatus, afterStatus)
                .set(TradeOrderDO::getSettleMethod, type));
    }

    default TradeOrderDO selectOrderByNoAndUserId(String no, Long userId) {
        return selectOne(new LambdaQueryWrapperX<TradeOrderDO>()
                .eq(TradeOrderDO::getOrderNo,no)
                .eqIfPresent(TradeOrderDO::getUserId, userId));
    }

    default PageResult<TradeOrderDO> selectPage(TradeOrderPageReqVO reqVO, Long userId) {
        return selectPage(reqVO, new LambdaQueryWrapperX<TradeOrderDO>()
                .eqIfPresent(TradeOrderDO::getUserId, userId)
                .inIfPresent(TradeOrderDO::getOrderType, reqVO.getOrderType())
                .eqIfPresent(TradeOrderDO::getMetalType, reqVO.getMetalType())
                .eqIfPresent(TradeOrderDO::getStatus, reqVO.getStatus())
                .eqIfPresent(TradeOrderDO::getPayStatus, reqVO.getPayStatus())
                .geIfPresent(TradeOrderDO::getStatus, reqVO.getStatusStart())
                .leIfPresent(TradeOrderDO::getStatus, reqVO.getStatusEnd())
//                .betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(TradeOrderDO::getCreateTime));
    }

    default PageResult<TradeOrderDO> selectPage(TradeOrderPageReqVO pageReqVO) {
        return selectPage(pageReqVO, new LambdaQueryWrapperX<TradeOrderDO>()
//                .eqIfPresent(TradeOrderDO::getUserId, userId)
                .inIfPresent(TradeOrderDO::getOrderType, pageReqVO.getOrderType())
                .eqIfPresent(TradeOrderDO::getMetalType, pageReqVO.getMetalType())
                .eqIfPresent(TradeOrderDO::getStatus, pageReqVO.getStatus())
                .eqIfPresent(TradeOrderDO::getPayStatus, pageReqVO.getPayStatus())
//                .betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(TradeOrderDO::getCreateTime));
    }

    default TradeOrderDO selectByNo(String orderNo){
        return selectOne(TradeOrderDO::getOrderNo, orderNo);
    }

    default TradeOrderDO selectOneByPickUpVerifyCode(String pickUpVerifyCode) {
        return selectOne(TradeOrderDO::getPickUpVerifyCode, pickUpVerifyCode);
    }

    @Select("SELECT" +
            "    COUNT(*) AS unsettledCount," +
            "    SUM(CASE WHEN order_type = 3 THEN weight ELSE 0 END) AS buyWeight," +
            "    SUM(CASE WHEN order_type = 4 THEN weight ELSE 0 END) AS sellWeight," +
            "    SUM(CASE WHEN order_type = 3 THEN metal_price ELSE 0 END) AS sellWeightOrderPrice," +
            "    SUM(CASE WHEN order_type = 4 THEN metal_price ELSE 0 END) AS reclaimWeightOrderPrice," +
            "    AVG(CASE WHEN order_type = 3 THEN order_price END) AS avgSellOrderPrice," +
            "    AVG(CASE WHEN order_type = 4 THEN order_price END) AS avgReclaimOrderPrice," +
            "    SUM(receive_deposit) AS totalDeposit," +
            "    SUM(receive_deposit_add) AS totalDepositAdd " +
            "FROM trade_order " +
            "WHERE " +
            "    order_type IN (3,4) " +
            "    AND deleted = 0  " +
            "    AND status BETWEEN 1 AND 30  " +
            " ;")
    TradeOrderSummaryRespVO getLockOrderSummary();

    @Select("SELECT count(*) from trade_order " +
            "WHERE status >30 AND status<>60 AND order_type IN(3,4) AND deleted = 0")
    Integer getLockOrderSettle();

    default List<TradeOrderDO> selectListByStatusAndCreateTimeLt(Integer status) {
        return selectList(new LambdaQueryWrapperX<TradeOrderDO>()
                .eq(TradeOrderDO::getStatus, status)
                .le(TradeOrderDO::getExpireTime, LocalDateTime.now()));
    }

    @Select("SELECT " +
            "    SUM(registerAudit) AS registerAudit," +
            "    SUM(paymentAudit) AS paymentAudit, " +
            "    SUM(fullPayOrder) AS fullPayOrder," +
            "    SUM(lockPriceOrder) AS lockPriceOrder," +
            "    SUM(exchangeOrder) AS exchangeOrder " +
            " FROM ( " +
            "    SELECT COUNT(*) AS registerAudit, 0 AS paymentAudit, 0 as fullPayOrder,0 as lockPriceOrder,0 as exchangeOrder " +
            "    FROM member_user WHERE status = 2" +
            "    " +
            "    UNION ALL" +
            "    " +
            "    SELECT 0, COUNT(*), 0,0,0" +
            "    FROM pay_collect_order WHERE status = 0" +
            "    UNION ALL" +
            "    " +
            "    SELECT 0,0," +
            "        SUM(CASE WHEN order_type = 1 THEN 1 ELSE 0 END)," +
            "        SUM(CASE WHEN order_type IN (3,4) THEN 1 ELSE 0 END), " +
            "        SUM(CASE WHEN order_type = 7 THEN 1 ELSE 0 END) " +
            "    FROM trade_order " +
            "    WHERE status BETWEEN 1 AND 30" +
            ") AS combined_data;")
    Map<String, Object> getIndexNumber();
    @Select("SELECT " +
            "  SUM(full_payment_count) AS fullPaymentCount," +
            "  SUM(full_payment_amount) AS fullPaymentAmount," +
            "  SUM(full_payment_avg_price) AS fullPaymentAvgPrice," +
            "  SUM(full_status_waiting) AS fullPaymentStatusWaiting," +
            "  SUM(full_status_pending) AS fullPaymentStatusPending," +
            "  SUM(full_status_shipped) AS fullPaymentStatusShipped," +
            "  SUM(full_status_completed) AS fullPaymentStatusCompleted," +
            "  SUM(lock_buy_weight) AS lockBuyWeight," +
            "  SUM(lock_sell_weight) AS lockSellWeight," +
            "  SUM(lock_settle_weight) AS lockSettleWeight," +
            "  SUM(price_lock) AS priceLock," +
            "  SUM(avg_price_lock_buy) AS avgPriceLockBuy," +
            "  SUM(avg_price_lock_sell) AS avgPriceLockSell," +
            "  SUM(exchange_count) AS exchangeCount," +
            "  SUM(exchange_amount) AS exchangeAmount, " +
            "  SUM(exchange_change_weight) AS exchangeChangeWeight, " +
            "  SUM(exchange_wait) AS exchangeWait, " +
            "  SUM(exchange_check) AS exchangeCheck, " +
            "  SUM(exchange_confirm) AS exchangeConfirm, " +
            "  SUM(exchange_completed) AS exchangeCompleted " +
            " FROM (" +
            "  SELECT " +
            "    COUNT(*) AS full_payment_count," +
            "    SUM(weight) AS full_payment_amount," +
            "    AVG(order_price) AS full_payment_avg_price," +
            "    SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) AS full_status_waiting," +
            "    SUM(CASE WHEN status = 40 THEN 1 ELSE 0 END) AS full_status_pending," +
            "    SUM(CASE WHEN status = 41 THEN 1 ELSE 0 END) AS full_status_shipped," +
            "    SUM(CASE WHEN status = 50 THEN 1 ELSE 0 END) AS full_status_completed," +
            "    0 AS lock_buy_weight, 0 AS lock_sell_weight, 0 AS lock_settle_weight, 0 AS price_lock, " +
            "    0 AS avg_price_lock_buy, 0 AS avg_price_lock_sell, 0 AS exchange_count, 0 AS exchange_amount, " +
            "    0 AS exchange_change_weight, 0 AS exchange_wait, 0 AS exchange_check, 0 AS exchange_confirm, " +
            "    0 AS exchange_completed " +
            "  FROM trade_order " +
            "  WHERE order_type = 1 " +
            "    AND deleted = 0" +
            "    AND create_time BETWEEN #{startTime} AND CURRENT_TIMESTAMP" +
            "  " +
            "  UNION ALL" +
            "  SELECT " +
            "    0, 0, 0, 0, 0, 0, 0," +
            "    SUM(CASE WHEN order_type = 3 THEN weight ELSE 0 END) AS lock_buy_weight," +
            "    SUM(CASE WHEN order_type = 4 THEN weight ELSE 0 END) AS lock_sell_weight," +
            "    SUM(CASE WHEN status > 40 THEN weight ELSE 0 END) AS lock_settle_weight," +
            "    SUM(metal_price) AS price_lock," +
            "    AVG(CASE WHEN order_type = 3 THEN order_price ELSE 0 END) AS avg_price_lock_buy," +
            "    AVG(CASE WHEN order_type = 4 THEN order_price ELSE 0 END) AS avg_price_lock_sell," +
            "    0, 0, 0, 0, 0, 0, 0 " +
            "  FROM trade_order " +
            "  WHERE order_type in (3,4) " +
            "    AND deleted = 0" +
            "    AND create_time BETWEEN #{startTime} AND CURRENT_TIMESTAMP" +
            "  " +
            "  UNION ALL" +
            "  SELECT " +
            "    0, 0, 0, 0, 0, 0, 0, " +
            "    0, 0, 0, 0, 0, 0, " +
            "    COUNT(*) AS exchange_count," +
            "    SUM(exchange_weight) AS exchange_amount," +
            "    SUM(CASE WHEN status > 40 THEN weight ELSE 0 END) AS exchange_change_weight," +
            "    SUM(CASE WHEN status > 10 AND status < 20 THEN 1 ELSE 0 END) AS exchange_wait," +
            "    SUM(CASE WHEN status = 20 THEN 1 ELSE 0 END) AS exchange_check," +
            "    SUM(CASE WHEN status = 23 THEN 1 ELSE 0 END) AS exchange_confirm," +
            "    SUM(CASE WHEN status = 50 THEN 1 ELSE 0 END) AS exchange_completed " +
            "  FROM trade_order " +
            "  WHERE order_type = 7 " +
            "    AND deleted = 0" +
            "    AND create_time BETWEEN #{startTime} AND CURRENT_TIMESTAMP" +
            ") AS aggregated_data;")
    Map<String, Object> getIndexOrderNumber(@Param("startTime") LocalDateTime startTime);

    @Select("SELECT " +
            "    t_order.* " +
            "FROM " +
            "    trade_order AS t_order " +
            "INNER JOIN " +
            "    pay_order_detail AS pod " +
            "    ON t_order.order_no = pod.order_no " +
            "WHERE " +
            "    pod.status = 0 " +
            "    AND pod.expire_time <= CURRENT_TIMESTAMP  " +
            "    AND t_order.status = 30 ")
    List<TradeOrderDO> selectSettlingAndPayExpireOrder();

    @Select("select COALESCE(SUM(weight), 0) from trade_order where deleted = 0 and order_type= #{policyType} and user_id= #{loginUserId} and status <= 30")
    BigDecimal queryWeightSumByTypeAndUser(Integer policyType, Long loginUserId);
}